package com.itheima.controller;

import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.constants.SystemConstants;
import com.itheima.common.enums.HttpCodeEnum;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.common.vo.ResultVo;
import com.itheima.wemedia.feign.WmMaterialFeign;
import com.itheima.wemedia.pojo.WmMaterial;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/dfs")
@Slf4j
@Api("分布式文件微服")
public class FileController {

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private FdfsWebServer webServer;

    @Autowired
    private WmMaterialFeign wmMaterialFeign;


    /**
     * 上传文件
     * @param multipartFile
     * @return
     */
    @PostMapping("/upload")
    public ResultVo updateFile(MultipartFile multipartFile){

        //0. 请求来源校验
        String origin = RequestContextUtil.getHeader(SystemConstants.USER_HEADER_FROM);
        if (StringUtils.isEmpty(origin)){
            // 没有值。则没有经过网关，属于非法请求
            return ResultVo.error(HttpCodeEnum.NO_OPERATOR_AUTH);
        }
        //1. 上传文件
        String originalFilename = multipartFile.getOriginalFilename();
        //获取扩展名
        String ext = StringUtils.getFilename(originalFilename);
        //1. 上传文件到fastdfs
        try {
            StorePath storePath = client.uploadFile(multipartFile.getInputStream(), multipartFile.getSize(), ext, null);
            //1.1 获取文件id
            String fileId = storePath.getFullPath();
            //2. 拼接文件的完整路径
            String fileFullPath = webServer.getWebServerUrl() + fileId;
            log.info("文件路径：" + fileFullPath);

            //远程调用保存素材
            if ("wemedia-pic".equals(origin)){
                addWmMaterial(fileId);
            }
            //3. 返回文件路径 {url: 完整路径}
            Map<String, Object> result = Collections.singletonMap("url",fileFullPath);
            return ResultVo.ok(result);
        } catch (IOException e) {
            log.error("上传文件失败!{}",originalFilename,e);
        }
        return ResultVo.bizError("上传文件失败!");
    }

    /**
     * 远程调用，添加素材
     * @param fileId
     */
    private void addWmMaterial(String fileId) {
        //1. 构建素材对象
        log.info("添加素材");
        WmMaterial pojo = new WmMaterial();
        pojo.setUrl(fileId);
        pojo.setType(0); // 0 图片
        pojo.setCreatedTime(LocalDateTime.now());
        pojo.setIsCollection(0); //0 不是收藏
        pojo.setUserId(RequestContextUtil.getUserId());
        ResultVo result = wmMaterialFeign.add(pojo);
        if (!result.isSuccess()){
            throw new LeadNewsException("上传素材失败!");
        }
    }

    /**
     * 下载多个文件
     * @param fileIds
     * @return
     */
    @PostMapping("/download")
    public ResultVo<List<byte[]>> download(@RequestBody List<String> fileIds){
        List<byte[]> list = new ArrayList<>();
        //下载
        if (!CollectionUtils.isEmpty(fileIds)){
            DownloadByteArray dba = new DownloadByteArray();
            list = fileIds.stream().map(fileId -> {
                // 解析文件id，获取分组及文件目录
                StorePath storePath = StorePath.parseFromUrl(fileId);
                return client.downloadFile(storePath.getGroup(),storePath.getPath(),dba);
            }).collect(Collectors.toList());
        }
        return ResultVo.ok(list);
    }

}
